﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace Money
{
    // TODO we need to udpate the interlocking between modes to prevent losing data or strange combination occuring
    public partial class CategoriseShortcutsForm : Form
    {
        private enum State
        {
            Add,
            Edit,
            View,
            Saved,
            Cancel
        }

        State _state = State.View;
        bool _formLoaded = false;

        private List<CategoriseShortcut> _shortcuts;
        private CategoriseShortcut _editingShortcut = null;

        private int _lastSelectedRow = -1;

        public CategoriseShortcutsForm(List<CategoriseShortcut> shortcuts, Categories categories)
        {
            InitializeComponent();

            _shortcuts = shortcuts;

            _grid.AutoGenerateColumns = false;

            _grid.DataSource = shortcuts;
            _typeColumn.DataSource = Enum.GetValues(typeof(Transaction.TransactionType));
            _typeColumn.DataPropertyName = "Type";
            _categoryColumn.DataSource = categories;
            _categoryColumn.DataPropertyName = "CategoryId";
            _categoryColumn.ValueMember = "Id";
            _categoryColumn.DisplayMember = "Name";

            _shortCutKeySelection.DataSource = Enum.GetValues(typeof (Keys));

            _categorySelection.DataSource = categories;
            _categorySelection.ValueMember = "Id";
            _categorySelection.DisplayMember = "Name";

            _typeSelection.DataSource = Enum.GetValues(typeof(Transaction.TransactionType));

            SetGridDataSource();

            _actionButton.Enabled = false;
        }

        private void PopulateEditingControls(CategoriseShortcut shortcut)
        {
            _shiftModifier.Checked = shortcut.ShortCut.Shift;
            _controlModifier.Checked = shortcut.ShortCut.Ctrl;
            _altModifier.Checked = shortcut.ShortCut.Alt;

            _shortCutKeySelection.SelectedItem = shortcut.ShortCut.KeyCode;

            _categorySelection.SelectedValue = shortcut.CategoryId;
            _typeSelection.SelectedItem = shortcut.Type;

            if (shortcut.CategoryId != null)
            {
                _enableCategory.Checked = true;
                _categorySelection.Enabled = true;
            }
            else
            {
                _enableCategory.Checked = false;
                _categorySelection.SelectedIndex = -1;
                _categorySelection.Enabled = false;
            }

            if (shortcut.Type != null)
            {
                _enableType.Checked = true;
                _typeSelection.Enabled = true;
            }
            else
            {
                _enableType.Checked = false;
                _typeSelection.SelectedIndex = -1;
                _typeSelection.Enabled = false;
            }

            _comment.Text = shortcut.Comment;
            _description.Text = shortcut.Description;
        }

        private void SetGridDataSource()
        {
            _grid.DataSource = null;
            _grid.DataSource = _shortcuts;
        }

        private void _actionButton_Click(object sender, EventArgs e)
        {
            if (_shortCutKeySelection != null)
            {
                CategoriseShortcut shortcut = null;

                switch (_state)
                {
                    case State.Edit:
                        shortcut = _editingShortcut;
                        break;

                    case State.Add:
                        shortcut = new CategoriseShortcut();
                        _shortcuts.Add(shortcut);
                        break;
                }

                CreateShortcut(shortcut);

                ClearControls();

                SetGridDataSource();

                _state = State.View;
            }
        }

        private void CreateShortcut(CategoriseShortcut shortcut)
        {
            shortcut.ShortCut.Shift = _shiftModifier.Checked;
            shortcut.ShortCut.Alt = _altModifier.Checked;
            shortcut.ShortCut.Ctrl = _controlModifier.Checked;

            try
            {
                shortcut.ShortCut.KeyCode = (Keys)_shortCutKeySelection.SelectedItem;
            }
            catch
            {
                shortcut.ShortCut.KeyCode = default(Keys);
            }

            shortcut.Comment = _comment.Text;
            shortcut.Description = _description.Text;

            if (_enableCategory.Checked)
            {
                try
                {
                    shortcut.CategoryId = (int)_categorySelection.SelectedValue;
                }
                catch
                {
                    shortcut.CategoryId = null;
                }
            }
            else
            {
                shortcut.CategoryId = null;
            }

            if (_enableType.Checked)
            {
                try
                {
                    shortcut.Type = (Transaction.TransactionType)_typeSelection.SelectedItem;
                }
                catch
                {
                    shortcut.Type = null;
                }
            }
            else
            {
                shortcut.Type = null;
            }
        }

        private void _clearButton_Click(object sender, EventArgs e)
        {
            ClearControls();
            EnableControls(true);
            _state = State.Add;
            _grid.ClearSelection();
        }

        private void ClearControls()
        {
            _shiftModifier.Checked = false;
            _controlModifier.Checked = false;
            _altModifier.Checked = false;

            _enableType.Checked = false;
            _enableCategory.Checked = false;

            _shortCutKeySelection.SelectedIndex = -1;

            _categorySelection.SelectedIndex = -1;
            _typeSelection.SelectedIndex = -1;

            _comment.Text = string.Empty;
        }


        private void _grid_CellMouseClick(object sender, DataGridViewCellMouseEventArgs e)
        {
            DataGridView grid = sender as DataGridView;

            if (grid == null)
            {
                return;
            }

            if (e.RowIndex < 0)
            {
                return;
            }

            switch (e.Button)
            {
                case System.Windows.Forms.MouseButtons.Left:
                    break;

                case System.Windows.Forms.MouseButtons.Right:
                    if (grid.SelectedRows.Count > 1)
                    {
                        deleteEntriesMenuItem.Text = "Delete Entries";
                    }
                    else
                    {
                        deleteEntriesMenuItem.Text = "Delete Entry";
                    }
                    contextMenu.Show(System.Windows.Forms.Cursor.Position);
                    break;
            }
        }

        private void deleteEntriesMenuItem_Click(object sender, EventArgs e)
        {
            DataGridView grid = _grid;

            if (grid != null)
            {
                if (grid.SelectedRows.Count > 0)
                {
                    DialogResult result = MessageBox.Show("Do you want to delete " + grid.SelectedRows.Count + " entries?", "Confirm Delete", MessageBoxButtons.YesNo, MessageBoxIcon.Question, MessageBoxDefaultButton.Button2);

                    if (result == System.Windows.Forms.DialogResult.Yes)
                    {
                        foreach (DataGridViewRow row in grid.SelectedRows)
                        {
                            CategoriseShortcut shortcut = row.DataBoundItem as CategoriseShortcut;

                            if (shortcut != null)
                            {
                                _shortcuts.Remove(shortcut);
                            }
                        }

                        ClearControls();
                        SetGridDataSource();
                    }
                }
            }
        }

        private void _descriptionGrid_SelectionChanged(object sender, EventArgs e)
        {
            bool compareShortcuts = true;

            if (!_formLoaded)
            {
                return;
            }

            // if last row is equal to -2 then this is a special case where we do not want to do anything as we are mid-operation
            if (_lastSelectedRow == -2)
            {
                return;
            }

            // if we have no selection then we can add a record
            if (_grid.SelectedRows.Count == 0)
            {
                EnableControls(true);
                ClearControls();
                _state = State.Add;
                _lastSelectedRow = -1;
            }
            // if we have one selection then we can change an entry
            else if (_grid.SelectedRows.Count == 1)
            {
                if (_lastSelectedRow == _grid.SelectedRows[0].Index)
                {
                    return;
                }

                CategoriseShortcut shortcut = _grid.SelectedRows[0].DataBoundItem as CategoriseShortcut;

                if (shortcut != null)
                {
                    PopulateEditingControls(shortcut);

                    EnableControls(true);
                    _state = State.Edit;
                    _editingShortcut = shortcut;
                    _lastSelectedRow = _grid.SelectedRows[0].Index;
                }
                else
                {
                    _lastSelectedRow = -1;
                    EnableControls(true);
                    ClearControls();
                    _state = State.Add;
                }
            }
            // if we have more than one then we cannot od anything other than delete so disable edit controls
            else
            {
                EnableControls(false);

                ClearControls();
                _state = State.View;
            }

            ConfigureActionButton();
        }

        /// <summary>
        /// This method is called when any data entry object is edited on the screen. Check if we should change control operation if we have a changed value
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ValidAfterEdit(object sender, EventArgs e)
        {
            ConfigureActionButton();
        }

        private void ConfigureActionButton()
        {
            switch (_state)
            {
                case State.Add:
                    _actionButton.Text = _state.ToString();
                    if (_shortCutKeySelection.SelectedIndex != -1 && 
                         (
                          (_enableType.Checked && _typeSelection.SelectedIndex != -1) ||
                          !string.IsNullOrWhiteSpace(_comment.Text) ||
                          (_enableCategory.Checked && _categorySelection.SelectedIndex != -1)
                         )
                        )
                    {
                        _actionButton.Enabled = true;
                    }
                    else
                    {
                        _actionButton.Enabled = false;
                    }
                    break;

                case State.Edit:
                    _actionButton.Text = _state.ToString();

                    if (EditChanged(_editingShortcut) &&
                         (
                          (_enableType.Checked && _typeSelection.SelectedIndex != -1) ||
                          !string.IsNullOrWhiteSpace(_comment.Text) ||
                          (_enableCategory.Checked && _categorySelection.SelectedIndex != -1)
                         )
                       )
                    {
                        _actionButton.Enabled = true;
                    }
                    else
                    {
                        _actionButton.Enabled = false;
                    }
                    break;

                default:
                    _actionButton.Enabled = false;
                    break;
            }
        }

        private bool EditChanged(CategoriseShortcut shortcut)
        {
            bool changed = false;
            CategoriseShortcut newShortcut = new CategoriseShortcut();
            
            CreateShortcut(newShortcut);

            // TODO we need to add comment check in here but it is complicated by the fact that comment can be null
            // TODO check not complete at present, simplified
            if (!shortcut.Equals(newShortcut))
            {
                changed = true;
            }

            return changed;
        }

        private void EnableControls(bool state)
        {
            _shortCutKeySelection.Enabled = state;
            _comment.Enabled = state;
            _shortCutKeySelection.Enabled = state;
            _shiftModifier.Enabled = state;
            _controlModifier.Enabled = state;
            _altModifier.Enabled = state;
        }

        private void _grid_DataError(object sender, DataGridViewDataErrorEventArgs e)
        {

        }

        private void CategoriseShortcutsForm_Load(object sender, EventArgs e)
        {
            _clearButton_Click(this, new EventArgs());
            ConfigureActionButton();
            _formLoaded = true;
        }

        private void _enableCategory_CheckedChanged(object sender, EventArgs e)
        {
            _categorySelection.Enabled = _enableCategory.Checked;
        }

        private void _enableType_CheckedChanged(object sender, EventArgs e)
        {
            _typeSelection.Enabled = _enableType.Checked;
        }

        private void _enable_click(object sender, EventArgs e)
        {
            ValidAfterEdit(sender, e);
        }

    }
}
